package com.yc.cloud.common.websocket.core;

import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.corundumstudio.socketio.SocketIONamespace;

import com.yc.cloud.common.websocket.dto.RoomMessageDto;
import com.yc.cloud.common.websocket.dto.SingleMessageDto;
import com.yc.cloud.common.websocket.service.SocketService;
import lombok.extern.slf4j.Slf4j;
import lombok.val;

import java.util.List;


/**
 * 自定义消息业务处理类
 */
@Slf4j
public class SocketMessageManager {

    private final List<SocketIONamespace> socketIONamespaceList;
    private final SocketService socketService;

    public SocketMessageManager(List<SocketIONamespace> socketIONamespaceList, SocketService socketService) {
        this.socketIONamespaceList = socketIONamespaceList;
        this.socketService = socketService;
    }

    public void addAllListener() {
        addGetOnlineUserListener();
        addSingleMessageListener();
    }

    /**
     * 点对点发送消息
     */
    private void addSingleMessageListener() {
        for (SocketIONamespace socketIONamespace : socketIONamespaceList) {
            socketIONamespace.addEventListener(SocketMessage.SEND_SINGLE_MESSAGE, String.class, (client, data, ackRequest) -> {
                log.info("收到点对点消息：{}", JSONUtil.toJsonStr(data));
                if (StrUtil.isEmpty(data)) {
                    log.error("点对点消息发送失败：消息内容为空");
                    ackRequest.sendAckData(SendMessageResult.failed(SocketErrorConstants.DISPLAY_EMPTY));
                    return;
                }
                //这边可能发送格式不正确，会报错,使用try catch拦截
                //解析发送数据
                val sendMessageDto = JSONUtil.toBean(data, SingleMessageDto.class);
                //设置发送者信息
                sendMessageDto.setSender(SocketClientInfoManager.getInstance().getDisplayParamsByClient(client));
                val result = socketService.sendSingleMessage(sendMessageDto);
                if (result.getCode() != SendMessageResult.SUCCESS_CODE) {
                    log.error("点对点消息发送失败：{}", result.getMsg());
                    return;
                }
                log.info("点对点消息发送成功,消息内容：{}", JSONUtil.toJsonStr(sendMessageDto));
                ackRequest.sendAckData(result);
            });
            socketIONamespace.addEventListener(SocketMessage.SEND_ROOM_MESSAGE, String.class, (client, data, ackRequest) -> {
                log.info("收到房间消息：{}", JSONUtil.toJsonStr(data));
                if (StrUtil.isEmpty(data)) {
                    log.error("房间消息发送失败：消息内容为空");
                    ackRequest.sendAckData(SendMessageResult.failed(SocketErrorConstants.ROOM_MESSAGE_EMPTY));
                    return;
                }
                //这边可能发送格式不正确，会报错,使用try catch拦截
                //解析发送数据
                val roomMessageDto = JSONUtil.toBean(data, RoomMessageDto.class);
                //设置发送者信息
                roomMessageDto.setSender(SocketClientInfoManager.getInstance().getDisplayParamsByClient(client));
                val result = socketService.sendRoomMessage(roomMessageDto);
                if (result.getCode() != SendMessageResult.SUCCESS_CODE) {
                    log.error("房间消息发送失败：{}", result.getMsg());
                    return;
                }
                log.info("房间消息发送成功,消息内容：{}", JSONUtil.toJsonStr(roomMessageDto));
                ackRequest.sendAckData(result);
            });
            socketIONamespace.addEventListener(SocketMessage.GET_SERVER_TIME, String.class, (client, data, ackRequest) -> {
                //解析发送数据
                val sendMessageDto = JSONUtil.toBean(data, SingleMessageDto.class);
                sendMessageDto.setContent(String.valueOf(System.currentTimeMillis()));
                sendMessageDto.setSender(SocketClientInfoManager.getInstance().getDisplayParamsByClient(client));
                val result = socketService.sendSingleMessage(sendMessageDto);
                ackRequest.sendAckData(result);
            });
        }
    }

    /**
     * 获取在线玩家列表
     */
    public void addGetOnlineUserListener() {
        for (SocketIONamespace socketIONamespace : socketIONamespaceList) {
            socketIONamespace.addEventListener(SocketMessage.GET_ONLINE_USERS, String.class, (client, data, ackRequest) -> {
                val playerList = socketService.getOnLineUsers();
                ackRequest.sendAckData(playerList);
            });
        }
    }
}
